<script setup>
import { checkIsMasterHost, checkUpdateState, getFileList, onFileUpload, onPackageDownload, onReadText, onRemoveFiles, onSendText } from '@/apis';
import VideoPlayer from '@/components/VideoPlayer/index.vue';
import { ActionSheet, Button, Checkbox, FloatingBubble, Loading, Overlay, Progress, showImagePreview, showNotify, showSuccessToast } from 'vant';
import { onMounted, ref, watchEffect } from 'vue';
import FileDetailed from '../components/FileDetailed/index.vue';
import FileIcon from '../components/FileIcon/index.vue';
import { fileSizeFormatted, isImageFile, isTextFile, isVideoFile } from '../utils/default-util.js';

const fileList = ref([])
const fileInput = ref(null)
const isSelectMode = ref(false)
const isSelectAll = ref(false)
const showFilePopup = ref(false);
const popupFileData = ref({});
const showUploadPopup = ref(false);
// 文件上传进度
const uploadProgressValue = ref(0);
// 全局加载提示
const globalLoadingState = ref(false);
// 返回APP按钮是否显示
const backAppShow = ref(false)
// 记录文件是否有更新
const currentUpdateTime = ref(-1)
// 长按事件
const longpressEventState = ref(false)
const longpressEventValue = ref(null)


/** 发送共享文本 */
const popupShareShow = ref(false)
const popupShareHtml = ref(null)
const popupShareText = ref('');
const sendShareState = ref(false)
const onSendShareOpened = async () => {
    try {
        const text = await navigator.clipboard.readText();
        popupShareText.value = text
    } catch (err) {
        console.error('读取剪切板内容出错', err)
        // showNotify({ type: 'danger', message: '读取剪切板内容出错' })
    }
    setTimeout(() => popupShareHtml.value.focus(), 300);
}
const onSendShareText = () => {
    const value = popupShareText.value
    if (!value || value.length <= 0) {
        return
    }
    sendShareState.value = true
    onSendText(encodeURIComponent(value)).then(response => {
        if (response.code == 0) {
            // showNotify({ type: 'success', message: '发送成功' })
            popupShareText.value = ''
            popupShareShow.value = false
            refreshFileList()
        } else {
            showNotify({ type: 'warning', message: response.msg })
        }
    }).catch(error => {
        showNotify({ type: 'danger', message: '发送失败' })
    }).finally(() => {
        sendShareState.value = false
    })
}


/** 显示共享文本 */
const popupTextShow = ref(false)
const popupTextData = ref('')
const onCopyShareText = async () => {
    try {
        await navigator.clipboard.writeText(popupTextData.value);
        popupTextShow.value = false
        showNotify({ type: 'success', message: '文本已复制到剪贴板' })
    } catch (err) {
        console.error(err)
        showNotify({ type: 'danger', message: '复制到剪贴板出错,请手动复制' })
    }
}
const onReadTextValue = (it) => {
    popupTextData.value = ''
    popupTextShow.value = true
    onReadText(it.url)
        .then(text => popupTextData.value = text)
        .catch((err) => showNotify({ type: 'danger', message: '加载内容失败' }))
}


/** 显示详细信息 */
const popupDetailedShow = ref(false)
const popupDetailedData = ref({})
const popupDetailedImages = ref([])
const popupDetailedVideos = ref([])
watchEffect(() => { // 监听文件列表同步更新图片列表
    popupDetailedImages.value = fileList.value.filter(it => isImageFile(it.name)).map(it => it.url)
    popupDetailedVideos.value = fileList.value.filter(it => isVideoFile(it.name)) // .map(it => it.url)
})
const popupDetailedVideo = ref(false)
const onItemClick = (it) => {
    if (isSelectMode.value) {
        it.isCheck = !it.isCheck
    } else {
        if (isImageFile(it.name)) {
            showImagePreview({
                images: popupDetailedImages.value,
                startPosition: popupDetailedImages.value.findIndex(url => it.url === url),
                closeable: true,
                showIndicators: true,
                loop: false,
            })
        } else if (isTextFile(it.name)) {
            onReadTextValue(it)
        } else if (isVideoFile(it.name)) {
            popupDetailedVideo.value = true
            popupDetailedData.value = JSON.parse(JSON.stringify(it))
        } else {
            popupDetailedShow.value = true
            popupDetailedData.value = JSON.parse(JSON.stringify(it))
        }
    }
}

// 刷新列表数据
const refreshFileList = async () => {
    getFileList().then(response => {
        if (response.code === 0) {
            fileList.value = conversionApiDataToUiData(response.data)
        } else {
            showNotify({ type: 'warning', message: response.msg })
        }
    }).catch(err => {
        showNotify({ type: 'danger', message: '加载文件列表错误' })
    })

    // 接口数据转换为界面数据，增加isCheck属性
    const conversionApiDataToUiData = (list) => {
        if (list && Array.isArray(list)) {
            list.forEach((it) => {
                it.isCheck = false
            })
        }
        return JSON.parse(JSON.stringify(list))
    }
}

/**
 * 单个下载
 */
const onSaveFile = () => {
    if (popupFileData.value) {
        const a = document.createElement('a')
        a.href = popupFileData.value.url
        a.download = popupFileData.value.name
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        showFilePopup.value = false
    } else {
        showNotify({ type: 'warning', message: '请选择要下载的文件' })
    }
}

/**
 * 全选
 */
const actionSelectAll = (checked) => {
    isSelectAll.value = checked
    fileList.value.forEach((it) => {
        it.isCheck = checked
    })
}

/**
 * 批量删除
 */
const actionSelectDelete = () => {
    const items = fileList.value.filter(it => it.isCheck)
    if (items.length <= 0) {
        return
    }
    globalLoadingState.value = true
    const names = items.map(it => it.name).join(',')
    const encodeNames = encodeURIComponent(names)
    onRemoveFiles(encodeNames)
        .then(response => {
            if (response.code == 0) {
                refreshFileList()
            } else {
                showNotify({ type: 'warning', message: response.msg })
            }
        }).catch(error => {
            showNotify({ type: 'danger', message: '删除失败' })
        }).finally(() => {
            globalLoadingState.value = false
        })
}


/**
 * 打包导出
 */
const actionSelectExport = () => {
    const items = fileList.value.filter(it => it.isCheck)
    if (items.length <= 0) {
        return
    }
    if (items.length === 1) {
        const a = document.createElement('a')
        a.href = items[0].url
        a.download = popupFileData.value.name
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        return  // 只有一个元素时直接下载
    }
    globalLoadingState.value = true
    const names = items.map(it => it.name).join(',')
    const encodeNames = encodeURIComponent(names)
    onPackageDownload(encodeNames).then(response => {
        if (response.code === 0) {
            const a = document.createElement('a')
            a.href = response.data;
            // a.download = `${new Date().getTime()}.zip`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            showSuccessToast('已经成功创建下载任务')
        } else {
            showNotify({ type: 'warning', message: response.msg })
        }
    }).catch(e => {
        showNotify({ type: 'danger', message: '导出失败' })
    }).finally(() => {
        globalLoadingState.value = false
    })
}

/**
 * 选择文件上传
 */
const onSelectClick = () => {
    fileInput.value.click();
}

/**
 * 执行文件上传
 */
const onSelectChange = () => {
    const files = fileInput.value.files;
    if (!files || files.length <= 0) {
        return
    }
    showUploadPopup.value = true

    onFileUpload(files, (progress) => {
        uploadProgressValue.value = progress
    }).then(xhr => {
        refreshFileList()
    }).catch(xhr => {
        showNotify({ type: 'danger', message: '文件上传出错' })
    }).finally(() => {
        showUploadPopup.value = false
    })
}

/**
 * 长按事件
 */
const onLongpress = (it, id) => {
    longpressEventState.value = true
    longpressEventValue.value = it
}

const onLongpressSelect = (it) => {
    if (it.name === '下载' && longpressEventValue.value) {
        const a = document.createElement('a')
        a.href = longpressEventValue.value.url
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
    } else {
        longpressEventState = false
    }
}

/**
 * 在主机的浏览器时跳转回APP
 */
const goBackApp = () => {
    window.location.href = 'shared://'
}

onMounted(async () => {
    checkIsMasterHost().then(state => backAppShow.value = state)

    setInterval(() => { // setInterval / setTimeout
        checkUpdateState().then(response => {
            if (response.code === 0 && response.data > currentUpdateTime.value) {
                currentUpdateTime.value = response.data
                refreshFileList()
            }
        })
    }, 2000);
})

</script>

<template>
    <FloatingBubble v-if="backAppShow" gap="10" axis="xy" magnetic="x" @click="goBackApp">
        <img src="../assets/logo.png" style="width: 50px;" />
    </FloatingBubble>

    <div v-if="showUploadPopup" style="width: 100%; position: fixed; top: 0; z-index: 100; padding: 4px 0;">
        <Progress :percentage="uploadProgressValue" stroke-width="8" color="#42B983" />
    </div>

    <div :style="{ marginTop: showUploadPopup ? '25px' : '0px' }">
        <div class="root-container">
            <div class="item-container" v-for="(it, id) in fileList" :key="id">
                <div v-longpress="() => onLongpress(it, id)"
                    :class="['item-layout', { 'item-layout-select': isSelectMode }, { 'item-layout-check': isSelectMode && it.isCheck }]"
                    @click="() => onItemClick(it)">
                    <FileIcon :filename="it.name" :style="{ display: block, width: '30px', height: '30px' }" />
                    <span>{{ it.name }}</span>
                    <input v-if="isSelectMode" type="checkbox" v-model="it.isCheck" />
                </div>
            </div>
        </div>
        <div v-if="!showUploadPopup" class="action-container">
            <div v-if="!isSelectMode" class="action-button">
                <span @click="() => { isSelectMode = true }">选择</span>
                <img src="../assets/home_action_add.png" @click="onSelectClick" />
                <span @click="() => popupShareShow = true">聊天</span>
            </div>
            <div v-else class="action-edit-container">
                <div class="action-edit">
                    <Checkbox v-model="isSelectAll" @change="actionSelectAll" icon-size="16px">全选&nbsp;</Checkbox>
                </div>
                <div class="action-edit">
                    <span @click="actionSelectDelete">&nbsp;删除&nbsp;</span>
                    <span @click="actionSelectExport">&nbsp;导出&nbsp;</span>
                </div>
                <div class="action-edit">
                    <span @click="() => { isSelectMode = false }">取消</span>
                </div>
            </div>
        </div>
        <input type="file" ref="fileInput" accept="*/*" style="display: none;" :onchange="onSelectChange" multiple />
    </div>

    <div v-if="showFilePopup" class="popup-container" @click="() => showFilePopup = false">
        <div>
            <FileIcon :filename="popupFileData.name" :style="{ display: block, width: '200px', height: '200px' }" />
            <span>{{ popupFileData.name }}</span>
            <span>{{ fileSizeFormatted(popupFileData.size) }}</span>
            <p @click="onSaveFile">导出保存</p>
        </div>
    </div>

    <!-- 显示文件信息 -->
    <Overlay v-bind:show="popupDetailedShow" @click="popupDetailedShow = false" z-index="100">
        <FileDetailed :data="popupDetailedData" />
    </Overlay>

    <!-- 发送共享文本 -->
    <ActionSheet v-model:show="popupShareShow" @opened="onSendShareOpened" title="共享文本 (如某多链接...)">
        <div style="padding: 10px;">
            <textarea ref="popupShareHtml" v-model="popupShareText" rows="10"
                style="width: 100%; box-sizing: border-box; padding: 15px; border-radius: 20px; border-color: #42B983;"
                placeholder="在这里键入文本..."></textarea>
            <div style="display: flex; justify-content: space-between; align-items: center;">
                <Button @click="() => { popupShareText = '' }" type="warning" block round
                    style="margin: 10px 10px 10px 0;">清空</Button>
                <Button @click="onSendShareText" :loading="sendShareState" type="success" block round
                    style="margin: 10px 0 10px 10px;">发送</Button>
            </div>
        </div>
    </ActionSheet>

    <!-- 显示共享文本 -->
    <ActionSheet v-model:show="popupTextShow" title="文本内容">
        <div style="padding: 10px;">
            <textarea v-model="popupTextData" rows="5"
                style="width: 100%; box-sizing: border-box; padding: 15px; border-radius: 20px; border-color: #42B983;"
                placeholder="在这里键入文本..."></textarea>
            <Button @click="onCopyShareText" type="success" block round style="margin: 10px 0;">复制内容</Button>
        </div>
    </ActionSheet>

    <Overlay :show="globalLoadingState" z-index="1000">
        <div style="display: flex; justify-content: center; align-items: center; height: 100%;">
            <Loading color="#ffffff" text-color="#ffffff" size="50" type="spinner" vertical>加载中...</Loading>
        </div>
    </Overlay>

    <ActionSheet v-model:show="longpressEventState" :actions="[{ name: '下载' }, { name: '取消' }]"
        @select="onLongpressSelect"></ActionSheet>

    <!-- 播放视频 -->
    <VideoPlayer :show="popupDetailedVideo" :video-list="popupDetailedVideos" :click-video="popupDetailedData"
        :video-index="0" :onClose="() => popupDetailedVideo = false" />
</template>

<style scoped lang="scss">
.back-button {
    position: fixed;
    left: 0;
    top: 25%;
    z-index: 100;
    background: #FFFFFF99;
    padding: 6px 16px 6px 4px;
    border: #42B983 1px solid;
    border-left: none;
    border-top-right-radius: 30px;
    border-bottom-right-radius: 30px;
    color: #42B983;

    :active {
        transform: scale(0.95);
    }
}

.root-container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(60px, 1fr)); // 1fr
    gap: 5px;
    padding-bottom: 150px;
    justify-content: start;
    margin: 5px;
}

.item-container {
    padding: 0;
    margin: 2px 0;
    max-width: 100px;

    :active {
        background-color: #efefef;
        transform: scale(0.95);
    }
}

.item-layout {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    width: 100%;
    padding: 8px 0;
    // aspect-ratio: 1/1;   // 保持宽高比

    span {
        display: block;
        width: 60%;
        padding: 4px 0;
        font-size: 10px;
        word-break: break-all;
    }

    input {
        position: absolute;
        top: 6px;
        right: 6px;
    }
}

.item-layout-select {
    outline: 1px solid #efefef;
}

.item-layout-check {
    background-color: #efefef;
}

.action-container {
    position: fixed;
    width: 100%;
    height: 150px;
    bottom: 0;
    z-index: 10;
    background: linear-gradient(to bottom, #ffffff33, #00000033);
}

.action-button {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 50px;

    img {
        width: 50px;
        // margin: 0 10px;
        aspect-ratio: 1/1;
        display: block;
        border-radius: 50px;
        background-color: white;
        z-index: 2;
    }

    img:active {
        transform: scale(0.90);
    }

    span {
        display: inline-block;
        border: 1px solid #42B983;
        font-size: 16px;
        background-color: white;
        z-index: 1;
        padding: 8px 16px;
        width: 50px;
    }

    span:active {
        transform: scale(0.90);
    }

    >span:first-child {
        border-right: none;
        border-top-left-radius: 30px;
        border-bottom-left-radius: 30px;
        margin-right: -8px;
    }

    >span:last-child {
        border-left: none;
        border-top-right-radius: 30px;
        border-bottom-right-radius: 30px;
        margin-left: -8px;
    }
}

.action-edit-container {
    margin: 50px auto 0 auto;
    width: 90%;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.action-edit {
    width: auto;
    background-color: white;
    border-radius: 50px;
    padding: 8px 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    // box-shadow: 0 0 1px 1px #eeeeee;
    border: #42B983 solid 1px;

    span {
        display: inline-block;
        flex-grow: 1;
        padding: 0 10px;
    }

    span:active {
        color: #42B983;
    }
}

.popup-container {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #000000aa;
    z-index: 999;
    display: flex;
    justify-content: center;
    align-items: center;

    div {
        margin-top: -100px;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;

        span {
            display: block;
            font-size: 16px;
            color: white;
            padding: 10px 50px;
            word-break: break-all;
        }

        p {
            color: white;
            border: #42B983 2px solid;
            background-color: #42B98366;
            padding: 10px;
            font-size: 14px;
            border-radius: 10px;
        }
    }
}
</style>